home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
L' Effet Pommier 3
/
L'Effet Pommier - Volume 03.iso
/
Programmation
/
gray image 2.1
/
write_xwd.cc
< prev
next >
Wrap
Text File
|
1995-05-30
|
7KB
|
271 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* Grayscale Image
*
* Write the image into the file in the X11 Window dump format
* and display it with xwud program
*
* $Id: write_xwd.cc,v 2.0 1995/03/09 15:24:11 oleg Exp oleg $
*
************************************************************************
*/
#include "image.h"
#include "endian_io.h"
#ifdef __GNUC__
#pragma implementation "x11wd.h"
#endif
#include "x11wd.h"
/*
*------------------------------------------------------------------------
* Writing of X11 WD data structures
*/
void X11XColor::write(EndianOut& outs) const
{
outs.write_long ( pixel );
outs.write_short( red );
outs.write_short( green );
outs.write_short( blue );
outs.write_byte ( flags );
outs.write_byte ( pad );
}
void X11XColor::write_gray_colormap(EndianOut& outs, const int ncolors)
{
for(register int i = 0; i < ncolors; i++)
{
X11XColor grayshade(i, ncolors == 256 ? ((long)i<<8) | i :
(((long)i<<16)-i)/(ncolors-1) );
grayshade.write(outs);
}
}
/*
*------------------------------------------------------------------------
* Class XWdump
* designed to contain the control info about the image
* as defined in the X Window Dump file
*/
class XWdump // All the info pertaining to the XWD file
: public X11WDFileHeader, public EndianOut {
private:
const IMAGE& image; // Image being processed
const char * title; // Title for the image in the file
void write_image_data(void);
public:
XWdump(const IMAGE& _image); // Constructor
void set_title(const char * user_title);
void write_image(const char * file_name);
};
/*
*------------------------------------------------------------------------
* Construct the XWdump
* by filling out the fields of the structure from the IMAGE
*/
XWdump::XWdump(const IMAGE& _image) : image(_image)
{
title = image.q_name();
assure(image.q_depth() <= 8,
"Sorry, the program cannot write images with depth > 8");
header_size = sizeof(X11WDFileHeader) + strlen(title) + 1;
file_version = X11WD_FILE_VERSION;
pixmap_format = ZPixmap;
pixmap_width = image.q_ncols();
pixmap_height = image.q_nrows();
xoffset = 0;
xbyte_order = MSBFirst; set_bigendian();
bitmap_bit_order = MSBFirst;
window_width = image.q_ncols();
window_height = image.q_nrows();
window_x = 0;
window_y = 0;
window_bdrwidth = 0;
pixmap_depth = 8;
bits_per_pixel = 8;
colormap_entries = 256;
ncolors = 256;
bytes_per_line = image.q_ncols();
bitmap_unit = 8;
bitmap_pad = 8;
visual_class = StaticGray;
red_mask = 0;
green_mask = 0;
blue_mask = 0;
bits_per_rgb = pixmap_depth;
}
/*
*------------------------------------------------------------------------
* Set up the title for the image
* image.name == "" && user title == "" ---> resulting title = ""
* image.name != "" && user title == "" ---> resulting title = image.name
* image.name == "" && user title != "" ---> resulting title = user title
* image.name != "" && user title != "" --->
* resulting title = "image name/user title"
*
* Note that XWdump::title has been already set to image.title.
* If it is changed, the XWdump::header_size should be modified as well
*/
void XWdump::set_title(const char * user_title)
{
if( strlen(user_title) == 0 )
return;
register int old_title_len = strlen(title);
if( strlen(title) == 0 ) // No image title
title = user_title;
else
title =
strcat(
strcat(
strcpy((char *)calloc(strlen(title)+1+strlen(user_title)+1,
sizeof(char)),title),
"/"),
user_title);
header_size += strlen(title) - old_title_len;
}
/*
*------------------------------------------------------------------------
* Writing the X window dump file
*/
void XWdump::write_image(const char * file_name)
{
open(file_name);
// Writing the header
write_long( header_size );
write_long( file_version );
write_long( pixmap_format );
write_long( pixmap_depth );
write_long( pixmap_width );
write_long( pixmap_height );
write_long( xoffset );
write_long( xbyte_order );
write_long( bitmap_unit );
write_long( bitmap_bit_order );
write_long( bitmap_pad );
write_long( bits_per_pixel );
write_long( bytes_per_line );
write_long( visual_class );
write_long( red_mask );
write_long( green_mask );
write_long( blue_mask );
write_long( bits_per_rgb );
write_long( colormap_entries );
write_long( ncolors );
write_long( window_width );
write_long( window_height );
write_long( window_x );
write_long( window_y );
write_long( window_bdrwidth );
write(title, strlen(title)+1); // Write out the dump name
X11XColor::write_gray_colormap(*this,ncolors);
write_image_data();
close();
}
/*
*------------------------------------------------------------------------
* Write out the pixel matrix
* with 'bits_per_pixel'representation
*/
void XWdump::write_image_data(void)
{
register card row, col;
const long int maxval = (1 << image.q_depth()) - 1;
const long int bigger_maxval = (1 << bits_per_pixel) - 1;
assure(maxval <= bigger_maxval,
"Cannot display image with too many bits per pixel");
// Using simplified procedure if possible
if( bits_per_pixel == 8 && image.q_depth() == 8 )
{
for( row = 0; row < pixmap_height; ++row )
for( col = 0; col < pixmap_width; ++col )
write_byte( image(row,col) );
return;
}
// Handle the general case if tricks don't
// work
for( row = 0; row < pixmap_height; ++row )
{
register int bitshift = 8 - bits_per_pixel;
register char byte = 0;
for( col = 0; col < pixmap_width; ++col )
{
register long s = image(row,col);
if( maxval != bigger_maxval )
s = (((long)s << bits_per_pixel)-s) / maxval;
byte |= s << bitshift;
bitshift -= bits_per_pixel;
if( bitshift < 0 )
{
write_byte( byte );
bitshift = 8 - bits_per_pixel;
byte = 0;
}
if( bitshift < 8 - (signed)bits_per_pixel )
write_byte( byte );
}
}
}
/*
*------------------------------------------------------------------------
* Root modules
* for writing the image and displaying it
*/
void IMAGE::write_xwd(const char * file_name,const char * title) const
{
is_valid();
message("\nPreparing XWD file with name '%s'\n",file_name);
XWdump XWdump(*this);
XWdump.set_title(title);
XWdump.write_image(file_name);
}
#ifndef __MWERKS__
// Display the image with 'xwud' program
void IMAGE::display(const char * title) const
{
register int kid_id; // ID of the kid process
if( getenv("DISPLAY") == (char *)0 ) // Bypass if isn't an X terminal
return;
assert( (kid_id = fork()) != -1 );
if( kid_id == 0 ) // We're in the kid process
{
write_xwd("| xwud",title);
exit(0);
}
}
#endif